#include "delay.h"
#include "usart3.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
#include "usart.h"
#include "stdlib.h"
#include "sys.h"
#include "encoder.h"
#include "math.h"
#include "timer.h"
//串口接收缓存区
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN个字节.
u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节

u8 Usarts3_Temporary_Receive[48]; //接收缓冲,最大USART3_MAX_RECV_LEN个字节.

vu16 USART3_RX_STA = 0;
int Receive_Queue = 0;          //   当前接收队列数
int Procesee_Receive_Queue = 0; //   当前处理事件对列数

//初始化IO 串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率
void usart3_init(u32 bound)
{

    NVIC_InitTypeDef NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // GPIOB时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //串口3时钟使能

    USART_DeInit(USART3); //复位串口3
    //USART3_TX   PB10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);          //初始化PB10

    //USART3_RX    PB11
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);                //初始化PB11

    USART_InitStructure.USART_BaudRate = bound;                                     //波特率一般设置为9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                     //字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;                          //一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;                             //无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 //收发模式

    USART_Init(USART3, &USART_InitStructure); //初始化串口  3
    USART_Cmd(USART3, ENABLE);                //使能串口 3

    //使能接收中断
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启中断

    //设置中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);                           //根据指定的参数初始化VIC寄存器

    USART3_RX_STA = 0; //清零
}

void USART3_IRQHandler(void)
{
    static u8 i_number = 0; //*****添加静态变量*****/
    u8 Res;
    // if(USART_GetFlagStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
    if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收到数据
    {
        Res = USART_ReceiveData(USART3); //(USART1->DR);  //读取接收到的数据

        switch (Frame_Sign_usart3.now_status)
        {
            // printf("Begining_Frame_Sign_usart3.now_status:%d\r\n",Frame_Sign_usart3.now_status);
        case Usart_Initial_number:
            if (Res == 0x0d)
            {
                Frame_Sign_usart3.now_status = Usart_0D;
                Usarts3_Temporary_Receive[0] = Res;
                i_number++;
            }
            else
            {
                Frame_Sign_usart3.now_status = Usart_Initial_number;
                i_number = 0;
            }
            break;
        case Usart_0D:
            if (Res == 0x0a)
            {
                Frame_Sign_usart3.now_status = Usart_0A;
                Usarts3_Temporary_Receive[1] = Res;
                i_number++;
            }
            else
            {
                Frame_Sign_usart3.now_status = Usart_Initial_number;
                i_number = 0;
            }
            break;
        case Usart_0A:
            Usarts3_Temporary_Receive[i_number] = Res;
            i_number++;
            //   printf("i_number:%d\r\n",i_number);
            if (i_number == 12)
            {
                if ((Usarts3_Temporary_Receive[11] == 0xa5) && (Usarts3_Temporary_Receive[10] == 0x5a)) //判断包尾
                {
                    Frame_Sign_usart3.now_status = Usart_All_Tail;
                    if (!Judge_CRC()) //判断收到一条完整的正确的包
                    {
                        if ((Receive_Queue * 12) < USART3_MAX_RECV_LEN) //若对列数小于20，代表队列数缓存未填满
                        {
                            for (u8 i = 0; i < 12; i++)
                            {
                                USART3_RX_BUF[Receive_Queue * 12 + i] = Usarts3_Temporary_Receive[i];
                            }
                            Receive_Queue++; //每次进入CRC这里，说明收到符合协议的数据，缓存里的待处理数据+1
                            Frame_Sign_usart3.now_status = Usart_Initial_number;
                            //    Frame_Sign_usart3.now_status = Usart_CRC;
                            i_number = 0;

                            Uart3Time.LastTime = Uart3Time.Cnt; //更新串口接收的当前时间，用以判断是否接收超时，是否出现通信故障
                        }
                        else //若缓存填满了，则不接收新的数据，当前收到的数据清零
                        {
                            Frame_Sign_usart3.now_status = Usart_Initial_number;
                            i_number = 0;
                        }
                    } //判断CRC
                    else
                    {
                        Frame_Sign_usart3.now_status = Usart_Initial_number;
                        i_number = 0;
                    }
                }
                else
                {
                    Frame_Sign_usart3.now_status = Usart_Initial_number;
                    i_number = 0;
                }
            }
            else if (i_number > 12)
            {
                i_number = 0;
                Frame_Sign_usart3.now_status = Usart_Initial_number;
            }
            else
                ;
            break;
            //     case Usart_All_Tail:
            //                if(!Judge_CRC())
            //                {
            //                 Frame_Sign_usart3.now_status=Usart_CRC;
            //                 i_number=0;
            //                }//判断CRC
            //                else{ Frame_Sign_usart3.now_status=Usart_Initial_number;}
            //     break;
        case Usart_Faile:
            i_number = 0;
            Frame_Sign_usart3.now_status = Usart_Initial_number;
            break;
        case Usart_CRC:
            if (Frame_Sign_usart3.now_status == Usart_CRC)
            {

                //               usart3_Receive_Data[i_number] = Res;
                //               i_number++;
                ;
            }
        default:
            i_number = 0;
            Frame_Sign_usart3.now_status = Usart_Initial_number;
            break;
            // printf("End_Frame_Sign_usart3.now_status:%d\r\n",Frame_Sign_usart3.now_status);
        }
    }
}

void USART_Receive_Queue_Extract(u8 *receive_buffer) //从接收缓存中提取一帧数据，并更新数组
{
    if (Receive_Queue != 0)
    {
        for (u8 i = 0; i < 12; i++)
        {
            usart3_Receive_Data[i] = receive_buffer[i]; //把接收到的一帧数据缓存到处理区域 ，始终处理队列里的第一条数据，即数组[0]-[11]这帧
        }

        //将整个队列整体向前移动12个字节    ，第一帧数据从[0]-[11]被提取出来，后面的队列向前移动
        for (u8 i = 0; i < (Receive_Queue - 1); i++)
        { //循环移动提取后的队列次数
            for (u8 a = 0; a < 12; a++)
            {
                receive_buffer[i * 12 + a] = receive_buffer[(i + 1) * 12 + a]; //把后一帧数据移动到前一帧
            }
        }
        //提取出来了一帧数据，则当前队列最后一帧数据补零清空
        for (u8 i = 0; i < 12; i++)
        {
            receive_buffer[(Receive_Queue - 1) * 12 + i] = 0x00; //将队列中最后一帧数据清零
        }
        Procesee_Receive_Queue = Receive_Queue; //置值为1，则代表当前接收到处理事件
        Receive_Queue = Receive_Queue - 1;      //队列数减一，代表提取完了一帧数据，队列数重新赋值
    }
    else
        Procesee_Receive_Queue = 0; //若当前接收对列数为0，则代表待处理事件为0
}

void UART3_Send_Array(unsigned char send_array[], unsigned char num) //两个参数 一是数组(的数据) 二是数组长度1-255
{
    unsigned char i = 0; //定义一个局部变量  用来 发送字符串 ++运算
    while (i < num)
    {
        USART_SendData(USART3, send_array[i]); //通过库函数  发送数据
        while (USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET)
            ; //等待发送完成。   检测 USART_FLAG_TC 是否置1；
        i++;  //值 加一
    }
}

void USART3_Send_Byte(unsigned char byte) //串口发送一个字节
{
    USART_SendData(USART3, byte); //通过库函数  发送数据
    while (USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET)
        ; //等待发送完成。   检测 USART_FLAG_TC 是否置1；
}

//串口3,printf 函数
//确保一次发送数据不超过USART3_MAX_SEND_LEN字节
void u3_printf(char *fmt, ...) //...表示可变参数（多个可变参数组成一个列表，后面有专门的指针指向他），不限定个数和类型
{
    u16 i, j;
    va_list ap;                               //初始化指向可变参数列表的指针
    va_start(ap, fmt);                        //将第一个可变参数的地址付给ap，即ap指向可变参数列表的开始
    vsprintf((char *)USART3_TX_BUF, fmt, ap); //将参数fmt、ap指向的可变参数一起转换成格式化字符串，放(char*)USART3_TX_BUF数组中，其作用同sprintf（），只是参数类型不同
    va_end(ap);
    i = strlen((const char *)USART3_TX_BUF); //此次发送数据的长度
    for (j = 0; j < i; j++)                  //循环发送数据
    {
        while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
            ;                                     //循环发送,直到发送完毕
        USART_SendData(USART3, USART3_TX_BUF[j]); //把格式化字符串从开发板串口送出去
    }
}

void USART3_RX_Data()
{
    u8 len = 0;
    if (USART3_RX_STA & 0x8000)
    {
        len = USART3_RX_STA & 0X7FFF; //得到此次接收到的数据长度
        USART3_RX_BUF[len] = 0;       //加入结束符

        if (len > USART3_MAX_RECV_LEN - 2)
        {
            len = USART3_MAX_RECV_LEN - 1;
            USART3_RX_BUF[len] = 0; //加入结束符
        }

        USART3_RX_BUF[USART3_MAX_RECV_LEN - 1] = 0x01;
        //      u3_printf("%s\r\n",USART3_RX_BUF);
        USART3_RX_STA = 0;
    }
}
